import os
import re
import subprocess

from sqlalchemy.orm import Session, joinedload
from model.cname import CName
from model.cdn_node import CdnNode
from schema.cname_schema import CNameCreate, CNameUpdate
import shutil



def get_a_record(db: Session, record_id: int):
    return (
        db.query(CName)
        .options(joinedload(CName.nodes))
        .filter(CName.id == record_id)
        .first()
    )


def get_a_records(db: Session, skip: int = 0, limit: int = 100):
    return (
        db.query(CName)
        .options(joinedload(CName.nodes))
        .offset(skip)
        .limit(limit)
        .all()
    )

def get_online(db: Session):
    return (
        db.query(CName)
        .options(joinedload(CName.nodes))
        .all()
    )


def create_a_record(db: Session, record: CNameCreate):
    # 创建 CName
    db_record = CName(
        domain=record.domain,
        ttl=record.ttl,
        status=record.status,
    )

    # 如果有 node_ids，查询并绑定节点
    if record.node_ids:
        nodes = db.query(CdnNode).filter(CdnNode.id.in_(record.node_ids)).all()
        db_record.nodes = nodes

    db.add(db_record)
    db.commit()
    db.refresh(db_record)
    return db_record


def update_a_record(db: Session, record_id: int, record: CNameUpdate):
    db_record = db.query(CName).filter(CName.id == record_id).first()
    if not db_record:
        return None

    db_record.domain = record.domain
    db_record.ttl = record.ttl
    db_record.status = record.status

    # 如果前端传了 node_ids，就更新多对多关系
    if record.node_ids is not None:
        db_nodes = db.query(CdnNode).filter(CdnNode.id.in_(record.node_ids)).all()
        db_record.nodes = db_nodes

    db.commit()
    db.refresh(db_record)
    return db_record


def delete_a_record(db: Session, record_id: int):
    db_record = db.query(CName).filter(CName.id == record_id).first()
    if not db_record:
        return None

    # 删除时也会自动清理中间表关系
    db.delete(db_record)
    db.commit()
    return db_record


def generate_zone_file(domain: str, nodes: list[CdnNode]):
    """
    根据 domain + 节点生成 BIND zone 文件内容
    """
    lines = [
        f"$ORIGIN {domain}.",
        f"""@ IN SOA ns.{domain}. admin.{domain}. (
        2025090201 ; serial
        3600       ; refresh
        1800       ; retry
        604800     ; expire
        86400 )    ; minimum TTL
  IN  NS  ns.{domain}.
"""
    ]

    # 添加节点 A 记录
    for node in nodes:
        lines.append(f"@ IN A {node.host}")

    return "\n".join(lines)


def update_corefile(domain: str, zone_path: str, corefile_path: str):
    if os.path.exists(corefile_path):
        with open(corefile_path, "r", encoding="utf-8") as f:
            existing_corefile = f.read()
    else:
        existing_corefile = """
. {
    forward . 8.8.8.8 1.1.1.1
    log
    errors
    cache 30
}
"""

    # 正则匹配完整的域名配置块（以 domain 开头的行）
    pattern = rf"^\s*{re.escape(domain)}\s*\{{"
    if not re.search(pattern, existing_corefile, flags=re.MULTILINE):
        domain_corefile = f"""
{domain} {{
    file {zone_path}
    log
    errors
    cache 30
}}
"""
        existing_corefile += domain_corefile

        with open(corefile_path, "w", encoding="utf-8") as f:
            f.write(existing_corefile)

        print(f"✅ Corefile 更新完成，新增 {domain}")
    else:
        print(f"⚠️ {domain} 已存在，未重复添加")

def remove_domain_from_corefile(domain: str, corefile_path: str):
    """
    从 Corefile 中删除指定 domain 的配置块
    """
    if not os.path.exists(corefile_path):
        print("⚠️ Corefile 不存在，跳过删除")
        return

    with open(corefile_path, "r", encoding="utf-8") as f:
        existing_corefile = f.read()

    # 正则匹配 domain 配置块，支持多行删除
    # 例如：example.com { ... }
    pattern = rf"^\s*{re.escape(domain)}\s*\{{[\s\S]*?\}}\s*"
    new_corefile, count = re.subn(pattern, "", existing_corefile, flags=re.MULTILINE)

    if count > 0:
        with open(corefile_path, "w", encoding="utf-8") as f:
            f.write(new_corefile.strip() + "\n")
        print(f"✅ 已从 Corefile 移除 {domain} 配置块")
    else:
        print(f"⚠️ Corefile 中未找到 {domain} 配置块，跳过删除")

def ensure_coredns_installed():
    """检查 CoreDNS 是否存在，如果不存在则安装"""
    # 假设 CoreDNS 二进制安装在 /usr/local/bin/coredns
    coredns_path = "/usr/local/bin/coredns"

    # 1. 检查是否已经安装
    if shutil.which("coredns") or os.path.exists(coredns_path):
        return True

    # 2. 没有就下载安装（以 Linux amd64 为例）
    try:
        url = "https://github.com/coredns/coredns/releases/latest/download/coredns_amd64.tgz"
        install_dir = "/usr/local/bin"
        tmp_file = "/tmp/coredns.tgz"

        print("CoreDNS 未安装，开始下载安装...")
        subprocess.run(["curl", "-L", "-o", tmp_file, url], check=True)
        subprocess.run(["tar", "-xvzf", tmp_file, "-C", "/tmp"], check=True)
        subprocess.run(["mv", "/tmp/coredns", install_dir], check=True)
        subprocess.run(["chmod", "+x", os.path.join(install_dir, "coredns")], check=True)
        print("CoreDNS 安装完成！")

        return True
    except Exception as e:
        raise RuntimeError(f"CoreDNS 安装失败: {e}")

def restart_coredns():
    """重启coredns"""
    try:
        # ensure_coredns_installed()
        subprocess.run(["systemctl", "restart", "coredns"], check=True)
        print("CoreDNS 服务已重启！")
    except Exception as e:
        print("重启 CoreDNS 服务失败:", e)